/*
 * @lc app=leetcode.cn id=341 lang=typescript
 *
 * [341] 扁平化嵌套列表迭代器
 */

// @lc code=start
/**
 * // This is the interface that allows for creating nested lists.
 * // You should not implement it, or speculate about its implementation
 * class NestedInteger {
 *     If value is provided, then it holds a single integer
 *     Otherwise it holds an empty nested list
 *     constructor(value?: number) {
 *         ...
 *     };
 *
 *     Return true if this NestedInteger holds a single integer, rather than a nested list.
 *     isInteger(): boolean {
 *         ...
 *     };
 *
 *     Return the single integer that this NestedInteger holds, if it holds a single integer
 *     Return null if this NestedInteger holds a nested list
 *     getInteger(): number | null {
 *         ...
 *     };
 *
 *     Set this NestedInteger to hold a single integer equal to value.
 *     setInteger(value: number) {
 *         ...
 *     };
 *
 *     Set this NestedInteger to hold a nested list and adds a nested integer elem to it.
 *     add(elem: NestedInteger) {
 *         ...
 *     };
 *
 *     Return the nested list that this NestedInteger holds,
 *     or an empty list if this NestedInteger holds a single integer
 *     getList(): NestedInteger[] {
 *         ...
 *     };
 * };
 */

//  思路：递归
//  通过hasNext进行惰性展开，即有下一个并且是list才展开
//  参考：https://mp.weixin.qq.com/s/uEmD5YVGG5LHQEmJQ2GSfw

class NestedIterator {
    list: NestedInteger[]
    constructor(nestedList: NestedInteger[]) {
        this.list = nestedList
    }

    hasNext(): boolean {
        while (this.list.length && !this.list[0].isInteger()) {
            const first = this.list.shift()!.getList()
            for (let i = first.length - 1; i >= 0; i--) {
                this.list.unshift(first[i])
            }
        }
        return !!this.list.length
    }

    next(): number {
        return this.list.shift()!.getInteger() ?? -1
    }
}

/**
 * Your ParkingSystem object will be instantiated and called as such:
 * var obj = new NestedIterator(nestedList)
 * var a: number[] = []
 * while (obj.hasNext()) a.push(obj.next());
 */
// @lc code=end


class NestedInteger {
    num: number | null
    list: NestedInteger[]
    constructor(value?: number) {
        this.num = value ?? null
        this.list = []
    };

    isInteger(): boolean {
        return this.num !== null
    };

    getInteger(): number | null {
        return this.num
    };

    setInteger(value: number) {
        this.num = value
    };

    add(elem: NestedInteger) {
        this.list.push(elem)
    };

    getList(): NestedInteger[] {
        return this.list
    };
}

const n1 = new NestedInteger()
n1.add(new NestedInteger(1))
n1.add(new NestedInteger(1))
const n2 = new NestedInteger(2)
const n3 = new NestedInteger()
n3.add(new NestedInteger(1))
n3.add(new NestedInteger(1))

const list = [n1, n2, n3]

const it = new NestedIterator(list)

while (it.hasNext()) {
    console.log(it.next())
}